[자바의 신] 10장: 자바에는 상속이라는 것이 있어요¶
상속¶
자바에서는 클래스를 상속할 수 있다. 이때 상속한 클래스를 '부모 클래스', 상속 받은 클래스를 '자식 클래스'라고 한다. 자식 클래스는 public과 protected로 선언된 부모 클래스의 변수와 메서드를 내가 갖고 있는 것처럼 사용할 수 있다.
상속은 다음과 같은 장점을 갖는다.
- 같은 기능을 반복 구현할 필요 없이 재 사용할 수 있게 해준다.
- 기능을 수정할 때, 부모 클래스만 수정하면 모든 자식 클래스에 변경 사항이 적용된다.
상속 문법¶
상속은 extends
키워드를 통해서 할 수 있다. 상속 받은 자식 클래스의 생성자가 호출되면 부모 클래스의 기본 생성자(매개 변수가 없는 생성자)도 함께 호출된다.
만약 부모 클래스의 생성자를 명시적으로 호출하고 싶다면 super()
를 자식 클래스 생성자의 최상단에서 호출 해주면 된다. super()
는 부모 클래스의 생성자를 호출한다는 의미를 갖는다(또한 super()
에 인자를 넘겨줄 수도 있다).
자식 클래스 생성자에서 super()
를 명시적으로 지정하지 않으면 컴파일 시 자동으로 super()
가 추가 된다.
// 예시: 리그 오브 레전드의 챔피언 클래스
public class Champion {
// 챔피언이 공통적으로 가져야 할 상태인 이름, 체력, 공격력, 방어력을 선언한다.
String name;
int hp;
int power;
int armor;
// 챔피언 생성자
public Champion(String name, int hp, int power, int armor) {
this.name = name;
this.hp = hp;
this.power = power;
this.armor = armor;
}
// 챔피언이 공통적으로 할 수 있는 행동을 메서드로 정의하였다.
public void attack(Champion enemy) {
enemy.reduceHp(power);
}
public void reduceHp(int damage) {
hp -= armor - damage;
}
}
// 챔피언을 상속한 가렌 클래스를 만들어줬다.
// 이렇게 공통적으로 사용하는 기능을 상속하여 코드의 재사용성을 높일 수 있다.
public class Garen extends Champion {
public Garen(String name, int hp, int power, int armor) {
super(name, hp, power, armor);
}
}
메서드 Overridng¶
메서드 오버라이딩이란 상속 받은 메서드를 자식 클래스에서 재정의하여 사용하는 것을 말한다. 이때 재 정의된 메서드는 다음과 같은 규칙을 따라야 한다.
- 리턴 타입, 메서드 이름, 매개변수의 타입과 개수가 같아야 한다.
- 접근 제어자의 범위가 더 넓어질 수는 있지만 좁아질 수는 없다(public한 부모 메서드를 private하게 오버라이딩 할 수 없다).
public class Parent {
String name;
public Parent(String name) {
this.name = name;
}
public void introduce(){
System.out.print("I'm " + name);
}
}
public class Child extends Parent {
public Child(String name){
super(name);
}
// 상속받은 introduce() 메서드를 오버라이딩 하였다.
public void introduce(){
System.out.print("My name is " + name);
}
}
public class MethodOverriding {
public static void main(String args[]){
Child child = new Child("Bangwon");
child.introduce(); // My name is Bandwon
}
}
!주의: 오버로딩(overloading)과 오버라이딩(overriding)의 차이점
- 오버로딩: 같은 클래스 내에서 같은 이름의 메서드를 여러개 정의하는 것으로, 각 메서드는 매개변수의 타입, 개수 또는 순서가 달라야 한다.
- 오버라이딩: 상속 받은 메서드를 재정의 하는 것으로, 메서드의 이름, 매개변수, 반환 타입이 부모 클래스의 메서드와 동일해야 한다.
참조자료형의 형변환¶
상속관계가 성립되면 객체끼리 형변환이 가능하다. 참조자료형의 형변환도 원시자료형의 형변환 같이 암묵적 형변환과, 명시적 형변환이 있다.
자식타입의 객체를 부모타입으로 변경할 때 암묵적 형변환이 이뤄진다. 이때 형변환을 당한 자식타입의 객체는 부모 클래스의 메서드만 사용할 수 있다. 다음은 암묵적 형변환의 예시이다.
Child child = new Child();
Parent parent = child;
부모타입의 객체를 자식타입으로 변경할 때는 명시적 형변환을 해야한다. 단 부모타입의 객체는 자식 클래스로 생성된 객체여야 한다.
- 형변환이 되는 예시
Parent parent = new Child();
Child child = (Child)parent;
- 형변환이 안되는 예시
Parent parent = new Parent();
Child child = (Child)parent;
여러가지 값을 처리하거나 매개변수로 값을 전달 할 때는 보통 부모의 클래스 타입으로 보낸다. 이렇지 않으면 배열과 같이 여러 값을 한번에 본래 때 타입별로 구분하여 메서드를 만들어야 하는 문제가 생길 수 있다.
따라서 부모의 클래스의 타입으로 값을 보낸 후 instanceof
예약어를 이용하여 자식 타입으로 형변환 한다.
아래는 형변환에 대한 예시다.
- Computer.java
public class Computer {
String modelName;
int battery
public Computer(String modelName, int battery){
this.modelName = modelName;
this.battery = battery;
}
}
- Macbook.java
public class Macbook extends Computer {
public Macbook(String modelName, int battery) {
super(modelName, battery);
}
public void airDrop(){
System.out.println("Success");
}
}
- GaluxyBook.java
public class GaluxyBook extends Computer {
public GaluxyBook(String modelName, int battery) {
super(modelName, battery);
}
public void quickShare(){
System.out.println("Success");
}
}
-
형변환을 사용하지 않은 예시
-
Charger.java
public class Charger {
public static void main(String args[]){
Charger charger = new Charger();
Macbook [] macbooks = new Macbook[2];
macbooks[0] = new Macbook("Macbook Air", 130);
macbooks[1] = new Macbook("Macbook Pro", 300);
GaluxyBook [] galuxybooks = new GaluxyBook[2];
galuxybooks[0] =new GaluxyBook("Galuxybook Pro", 180);
galuxybooks[1] = new GaluxyBook("Galuxybook Go", 110);
charger.charge(macbooks);
charger.charge(galuxybookx);
}
public void charge(Macbook macbooks) {
for(Macbook macbook: macbooks) {
macbook.battery = 100;
macbook.airDrop();
}
}
public void charge(GaluxyBook galuxybooks) {
for(GaluxyBook galuxybook: galuxybooks) {
galuxybook.battery = 100;
galuxybook.quickshare();
}
}
}
-
형변환을 사용한 예시
-
Charger.java
public class Charger {
public static void main(String args[]){
Charger charger = new Charger();
Computer [] computers = new Computer[4];
computers[0] = new Macbook("Macbook Air", 130);
computers[1] = new Macbook("Macbook Pro", 300);
computers[3] = new GaluxyBook("Galuxybook Pro", 180);
computers[4] = new GaluxyBook("Galuxybook Go", 110);
charger.charge(computers);
}
public void charge(Computer computers) {
for(Computer computer: computers) {
computer.battery = 100;
if(computer instanceof Macbook) {
Macbook macbook = (Macbook) computer;
macbook.airDrop();
}else {
Galuxybook galuxybook = (Galuxybook) computer;
galuxybook.quickshare();
}
}
}
}
다형성¶
다형성(polymorphsim)이란 형태가 다양하다는 의미. 형 변환을 하더라도, 실제 호출되는 것은 원래 객체에 있는 메서드가 호출된다.
내용 더 추가할 것